package com.baoteng.ui.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.baoteng.ui.R;

/**
 * 弧形进度条
 * Author: loren
 * Date: 2019/9/3
 */
public class ArcSeekView extends View {

    //布局获取的属性
    int wholeArcColor;//整条圆弧颜色
    float arcWidth;//圆弧粗细
    Drawable potBg;//进度圆点背景
    float potWidth;//进度圆点的宽(直径)
    float seekWidth;//圆弧的宽(直径)
    int seekArcColor;//进度圆弧颜色
    int scaleType;//刻度类型，白点（0）或者白线(1)
    float maxSeek;//最大进度，默认100
    boolean showNumber = true;//是否显示中间进度数值
    String seekText;//中间数值
    int textColor;//中间数值字体颜色
    float textSize;//中间数值字体大小


    //计算或定义的属性
    RectF rectF;//圆弧所在整圆范围
    Rect center;//圆心坐标
    float progress = 0;//默认初始进度值
    private float startAngle = 165;
    private float sweepAngle = 210;
    Paint wholePaint;
    Paint seekPaint;
    Paint scalePotPaint;
    boolean isDrag = false;
    int[] location;
    int[] scalePot;
    int[] endLine;

    public ArcSeekView(Context context) {
        this(context, null);
    }

    public ArcSeekView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ArcSeekView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public ArcSeekView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initAttribute(attrs);
        initData();
    }

    private void initAttribute(AttributeSet attrs) {
        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.ArcSeekView);
        wholeArcColor = ta.getColor(R.styleable.ArcSeekView_whole_arc_color, getResources().getColor(R.color.black));
        arcWidth = ta.getDimension(R.styleable.ArcSeekView_arc_stoken_width, getResources().getDimension(R.dimen.arc_default_stoken_width));
        potBg = ta.getDrawable(R.styleable.ArcSeekView_seek_pot_background);
        if (potBg == null) {
            potBg = getResources().getDrawable(R.drawable.default_pot);
        }
        potWidth = ta.getDimension(R.styleable.ArcSeekView_seek_pot_width, getResources().getDimension(R.dimen.seek_pot_width));
        seekWidth = ta.getDimension(R.styleable.ArcSeekView_seek_width, getResources().getDimension(R.dimen.seek_default_width));
        seekArcColor = ta.getColor(R.styleable.ArcSeekView_seek_arc_color, getResources().getColor(R.color.withe));
        scaleType = ta.getInt(R.styleable.ArcSeekView_scale_type, 0);
        maxSeek = ta.getFloat(R.styleable.ArcSeekView_max_seek, 100f);
        showNumber = ta.getBoolean(R.styleable.ArcSeekView_show_progress_number, true);
        seekText = ta.getString(R.styleable.ArcSeekView_progress_text);
        if (seekText == null) {
            seekText = "";
        }
        textColor = ta.getColor(R.styleable.ArcSeekView_progress_text_color, getResources().getColor(R.color.withe));
        textSize = ta.getDimension(R.styleable.ArcSeekView_progress_text_size, getResources().getDimension(R.dimen.seek_text_size));
    }

    private void initData() {
        rectF = new RectF();
        //因为弧线有宽度，进度点宽度更大一些，故坐标需把这些宽度考虑进去
        rectF.left = potWidth / 2;
        rectF.top = potWidth / 2;
        rectF.right = seekWidth - potWidth / 2;
        rectF.bottom = seekWidth - potWidth / 2;

        center = new Rect();
        center.left = (int) (seekWidth / 2);
        center.top = (int) (seekWidth / 2);
        center.right = (int) (seekWidth / 2);
        center.bottom = (int) (seekWidth / 2);

        wholePaint = new Paint();
        wholePaint.setColor(wholeArcColor);
        wholePaint.setAntiAlias(true);
        wholePaint.setStyle(Paint.Style.STROKE);
        wholePaint.setStrokeWidth(arcWidth);
        wholePaint.setStrokeCap(Paint.Cap.ROUND);

        seekPaint = new Paint();
        seekPaint.setColor(seekArcColor);
        seekPaint.setAntiAlias(true);
        seekPaint.setStyle(Paint.Style.STROKE);
        seekPaint.setStrokeWidth(arcWidth);
        seekPaint.setStrokeCap(Paint.Cap.ROUND);

        scalePotPaint = new Paint();
        scalePotPaint.setColor(getResources().getColor(R.color.withe));
        scalePotPaint.setAntiAlias(true);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制整弧
        canvas.drawArc(rectF, startAngle, sweepAngle, false, wholePaint);
        if (isDrag) {
            // TODO: 2019/9/5 待优化
            //拖动状态下只需重绘进度，避免多余重复绘制(可使用另一个view绘制进度叠加在主view上层)
        }
        //绘制进度圆弧
        canvas.drawArc(rectF, startAngle, sweepAngle * (progress / maxSeek), false, seekPaint);
        //绘制进度圆点位置
        //根据圆心坐标及圆心角计算出圆上坐标
        location = calculateBounds(progress, (seekWidth - potWidth) / 2);
        potBg.setBounds((int) (location[0] - (potWidth / 2)), (int) (location[1] - (potWidth / 2)), (int) (location[0] + (potWidth / 2)), (int) (location[1] + (potWidth / 2)));
        potBg.draw(canvas);
        //绘制刻度
        if (scaleType == 0) {
            //白点型刻度
            for (int i = 0; i < 5; i++) {
                scalePot = calculateBounds(maxSeek / 4 * i, (seekWidth / 2) - 25);
                canvas.drawCircle(scalePot[0], scalePot[1], 3, scalePotPaint);
            }
        } else if (scaleType == 1) {
            //白线型刻度
            for (int i = 0; i < 21; i++) {
                //线的长度等于以下35-25
                scalePot = calculateBounds(maxSeek / 21 * i, (seekWidth / 2) - 25);
                endLine = calculateBounds(maxSeek / 21 * i, (seekWidth / 2) - 35);
                canvas.drawLine(scalePot[0], scalePot[1], endLine[0], endLine[1], scalePotPaint);
            }
        }
    }

    private int[] calculateBounds(float pro, float radius) {
        //计算progress所在圆上点坐标
        float angle = sweepAngle * (pro / maxSeek);
        float[] circle = {center.left, center.top};//圆心x\y坐标
        //假设圆心为原点，x正轴定为0度方向，根据所求点与圆心连线对0度轴的夹角，计算得出改点坐标
        int x = 0;
        int y = 0;
        //progress对0度夹角
        float mAngle = startAngle + angle;
        if (mAngle >= 360) {
            mAngle = mAngle - 360;
        }
        if (mAngle < 90) {
            x = (int) (circle[0] + (Math.cos(mAngle / 180 * Math.PI) * radius));
            y = (int) (circle[1] + (Math.sin(mAngle / 180 * Math.PI) * radius));
        } else if (mAngle >= 90 && mAngle < 180) {
            x = (int) (circle[0] - (Math.cos((1 - mAngle / 180) * Math.PI) * radius));
            y = (int) (circle[1] + (Math.sin((1 - mAngle / 180) * Math.PI) * radius));
        } else if (mAngle >= 180 && mAngle < 270) {
            x = (int) (circle[0] - (Math.cos((mAngle / 180 - 1) * Math.PI) * radius));
            y = (int) (circle[1] - (Math.sin((mAngle / 180 - 1) * Math.PI) * radius));
        } else if (mAngle >= 270 && mAngle < 360) {
            x = (int) (circle[0] + (Math.cos((2 - mAngle / 180) * Math.PI) * radius));
            y = (int) (circle[1] - (Math.sin((2 - mAngle / 180) * Math.PI) * radius));
        }
        int[] res = {x, y};
        return res;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:

                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();
                //如果x\y在响应范围内（接触点坐标与圆心连线小于最小响应半径90）
                double d = Math.sqrt(Math.pow((x - center.left), 2) + Math.pow((y - center.top), 2));
                if (d > 80 && d < (seekWidth / 2)) {
                    //计算拖动的progress（根据接触点与圆心连线相对圆弧起始弧度的夹角得出）
                    double xDistance = Math.abs(x - center.left);
                    double yDistance = Math.abs(center.left - y);
                    double angle = (Math.atan(yDistance / xDistance)) / Math.PI * 180;
                    float ckAngle = (sweepAngle - 180) / 2;
                    if (x > center.left && y < center.top) {
                        //在第一象限
                        progress = (float) ((sweepAngle - (ckAngle + angle)) / sweepAngle * maxSeek);
                    } else if (x < center.left && y < center.top) {
                        //在第二象限
                        progress = (float) ((ckAngle + angle) / sweepAngle * maxSeek);
                    } else if (x < center.left && y > center.top) {
                        //在第三象限
                        progress = (float) ((ckAngle - angle) / sweepAngle * maxSeek);
                    } else if (x > center.left && y > center.top) {
                        //在第四象限
                        progress = (float) ((sweepAngle - (ckAngle - angle)) / sweepAngle * maxSeek);
                    }
                    if (progress >= 0 && progress <= maxSeek) {
                        callBackSeek();
                        invalidate();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                callBackSeekFinish();
                break;
        }
        return true;
    }

    //外部调用的函数=====================================================
    public void setProgress(float f) {
        if (f <= 0) {
            progress = 0;
            callBackSeekFinish();
            invalidate();
            return;
        }
        if (f >= maxSeek) {
            progress = maxSeek;
            callBackSeekFinish();
            invalidate();
            return;
        }
        progress = f;
        callBackSeekFinish();
        invalidate();
    }

    public void reduceProgress() {
        float f = progress - 1;
        setProgress(f);
    }

    public void addProgress() {
        float f = progress + 1;
        setProgress(f);
    }

    public float getProgress() {
        return progress;
    }

    //外部调用的函数=====================================================

    private void callBackSeek() {
        if (listener != null) {
            if (progress <= 0) {
                listener.onSeek(0);
            } else if (progress >= maxSeek) {
                listener.onSeek(maxSeek);
            } else {
                listener.onSeek(progress);
            }
        }
    }

    private void callBackSeekFinish() {
        if (listener != null) {
            if (progress <= 0) {
                listener.onSeekFinish(0);
            } else if (progress >= maxSeek) {
                listener.onSeekFinish(maxSeek);
            } else {
                listener.onSeekFinish(progress);
            }
        }
    }

    private OnSeekChangeListener listener;

    public void setOnSeekChangeListener(OnSeekChangeListener listener) {
        this.listener = listener;
    }

    public interface OnSeekChangeListener {
        void onSeek(float progress);

        void onSeekFinish(float progress);
    }
}
